<!DOCTYPE html>
<!-- Copyright © 2021~2022 by wzh -->
<html lang="zh">
	<head>
		<meta charset="UTF-8" />
		<meta content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" name="viewport" />
		<title>多人联机 | 五子棋</title>
		
		<!--icon-->
		<link href="./img/icon.png" rel="icon" type="image/x-icon"/>
		
		<!-- 异步fonts加载 -->
		<script src="./js/webfontloader.js"></script>
		<script>
		if (typeof require != "undefined"){ //electron
			console.log("electron")
			document.write(`<link href="./css/fonts.css" rel="stylesheet" type="text/css" />`);
			window.onload = function(){
				console.log("onload")
				$("body").addClass("wf-active");
			}
		}else{
			WebFont.load({
				google: {
					families: ["kt", "st", "xs", "zyyt"],
					api: "./css/fonts.css"
				}
			});
		}
		</script>
		
		<style>
		/* 字体缩放方案 */
		/* @media screen and (max-width:320px){
			body {font-size: calc(0.018 * 320px + 6px) !important;}
		}
		body{
			font-size: calc(1.8vw + 6px) !important;
		}
		@media screen and (min-width: 960px){
			body {font-size: calc(0.018 * 960px + 6px) !important;}
		} */
		
		/* element */
		*{
			outline: none; /* 无点击线 */
		}
		html{
			/* 禁止选择 */
			-moz-user-select: none;
			-khtml-user-select: none;
			user-select: none;
			
			background: #fffae8; /* 背景 */
		}
		html.outDown{
			min-height: 100%;
			background: #fffae8 url("./img/background.jpg") no-repeat fixed center;
			background-size: cover;
			max-width: 100%;
			margin: auto;
			
			overflow-y: hidden;
		}
		html.outHeight{
			overflow-y: hidden;
		}
		
		body{
			position: absolute;
			width: 100%;
			height: 100%;
			left: 0;
			top: 0;
			margin: 0;
			padding: 0;
			overflow-x: hidden;
			
			background: #fffae8; /* 背景 */
			
			opacity: 0; /* 完全透明 */
			transition: opacity 1s, top 0.6s; /* 出入动画 */
		}
		html.fadeIn > body{
			opacity: 1; /* 不透明 */
		}
		html.outDown > body{
			top: 100%; /* 下滑 */
			overflow-y: hidden;
		}
		html.outHeight > body{
			height: 0%; /* 高度减小 */
			overflow-y: hidden;
		}
		
		/* layui */
		.layui-btn-group .layui-btn:not(:first-child){
			border-left-style: none !important;
		}
		
		/*   列表   */
		/* header */
		body > header{
			display: flex;
			width: 100%;
			background-color: #aef;
		}
		body > header > i{
			flex: none;
			padding: 0.3rem;
			font-size: 2.5em !important;
			font-weight: bold;
			
			background-color: #aef;
			border: none;
			transition: background-color 0.3s;
		}
		body > header > i:focus{
			background-color: #afe;
		}
		body > header > i:active{
			background-color: #9ed;
		}
		body > header > h1{
			display: inline-block;
			width: 100%;
			margin: 0;
			padding: 10px 0;
			font-size: 2em;
			font-weight: bold; /* 粗体 layui */
			text-align: center;
		}
		
		/* state */
		.state{
			flex: none;
			margin: 0;
			padding: 0;
			text-align: center;
		}
		.state.connecting{
			background-color: yellow;
			color: red;
		}
		.state.success{
			/*display: none;*/
			background-color: blue;
			color: white;
		}
		.state.failed{
			background-color: red;
			color: white;
		}
		
		/* people */
		footer{
			display: block;
			position: fixed;
			bottom: 0;
			width: 100%;
			text-align: center;
			background-color: #aaa;
			color: #fff;
		}
		
		/* rooms */
		#rooms{
			margin: 1rem;
			font-size: 1.3em;
			text-align: center;
		}
		#rooms > li{
			margin: 1rem 0.6rem;
			padding: 0.6rem;
			transition: background-color 0.2s;
		}
		#rooms > li.able{
			border: 1px solid #6af;
			background-color: #def;
		}
		#rooms > li.able:active{
			background-color: #cde;
		}
		#rooms > li.unable{
			border: 1px solid #fa6;
			background-color: #fed;
		}
		#rooms > li.unable:active{
			background-color: #edc;
		}
		#rooms > li > h3{
			margin: 0.3rem 0;
			font-weight: bold;
		}
		#rooms > li > p{
			font-size: 0.9em;
		}
		
		
		/*   房间   */
		#room{
			position: absolute;
			width: 100%;
			height: 100%;
			left: 0;
			top: 0;
			
			display: flex;
			flex-direction: column;
			
			background: #fffae8;
			font-size: 1em;
		}
		#room > *:not(.fill){
			flex: none;
		}
		
		/* header */
		#room > header{
			display: flex;
			width: 100%;
			background-color: #aef;
		}
		#room > header > i{
			flex: none;
			padding: 0.3rem;
			font-size: 2.5em !important;
			font-weight: bold;
			
			background-color: #aef;
			border: none;
			transition: background-color 0.3s;
		}
		#room > header > i:focus{
			background-color: #afe;
		}
		#room > header > i:active{
			background-color: #9ed;
		}
		#room > header > h2{
			display: inline-block;
			width: 100%;
			margin: 0;
			padding: 10px 0;
			font-size: 2em;
			text-align: center;
			font-weight: bold;
		}
		
		/* label */
		#room > label{
			margin: 1rem;
			margin-top: 1.6rem;
			margin-bottom: 0.3rem;
			font-size: 1.3em;
			font-weight: bold;
		}
		
		/* ul */
		#players{
			margin: 0.3rem;
			font-size: 1.1em;
			text-align: center;
		}
		#players > li{
			margin: 0.6rem;
			padding: 0.6rem;
			background-color: #68a;
			color: #fff;
			border-radius: 2px;
		}
		
		/* form */
		#room > form{
			padding-right: 0.6rem;
			font-size: 1.1em;
		}
		
		/* info */
		#info{
			display: flex;
			flex-direction: column;
			margin: 8px;
		}
		#info > .output{
			height: 160px;
			overflow-y: auto;
		}
		#info > .output > p{
			margin: 0;
			font-size: 0.9em;
		}
		#info > .input{
			display: flex;
			margin-top: 0.5rem;
		}
		#info > .input > input{
			width: 100%;
			margin-right: 0.2rem;
		}
		#info > .input > input:focus{
			border: 1px solid rgb(210, 210, 210);
		}
		#info > .input > button{
			flex: none;
			margin-left: 0.2rem;
		}
		
		/* fill */
		/*#room > .fill{
			height: 100%;
		}*/
		
		/* buttons */
		#room > button{
			width: 80vw;
			margin: 1rem auto;
		}
		</style>
		
		<!-- jquery -->
		<script src="./js/jquery.min.js"></script>
		<script>
		if (typeof require != "undefined") //electron
			window.$ = window.jQuery = require("./js/jquery.min.js");
		</script>
		
		<!-- 语言包 -->
		<script src="./lang/lang.js" defer></script>
		
		<!-- layui -->
		<!--<link rel="stylesheet" href="https://unpkg.com/layui@2.6.4/dist/css/layui.css">
		<script src="https://unpkg.com/layui@2.6.8/dist/layui.js"></script>-->
		<script src="./layui/layui.js"></script>
		<link rel="stylesheet" href="./layui/css/layui.css">
		
		<!-- 调试工具 -->
		<!-- <script src="https://cdn.jsdelivr.net/npm/eruda"></script>
		<script src="https://cdn.bootcss.com/vConsole/3.3.4/vconsole.min.js"></script>
		<script>
		if ( /ipad|iphone|midp|rv:1.2.3.4|ucweb|android|windows ce|windows mobile/.test( navigator.userAgent.toLowerCase() ) ){
			//手机
			eruda.init();
			new VConsole();
		}
		</script> -->
		
		<!-- PianoMusic Bgm -->
		<script src="./js/acoustic_grand_piano-ogg.js"></script>
		<script src="./js/music.js"></script>
		<script src="./js/bgm.js"></script>
		
		<script src="https://wzh.glitch.me/socket.io/socket.io.js"></script> <!-- socket -->
		
		<script src="./js/js_plus.min.js"></script> <!-- js+ -->
		
		<script src="https://wzh656.github.io/gobang/js/dynamic.js" async></script>
		<script src="https://wzh656.github.io/gobang/js/count.js" async></script>
		<script>
		var _hmt = _hmt || [];
		(function() {
			var hm = document.createElement("script");
			hm.src = "https://hm.baidu.com/hm.js?c6b8f0ad7ec671e54d83e86a67280999";
			var s = document.getElementsByTagName("script")[0]; 
			s.parentNode.insertBefore(hm, s);
		})();
		</script>
		
		<!-- Global site tag (gtag.js) - Google Analytics -->
		<script async src="https://www.googletagmanager.com/gtag/js?id=G-WTWJEHK1C2"></script>
		<script>
		window.dataLayer = window.dataLayer || [];
		function gtag(){dataLayer.push(arguments);}
		gtag('js', new Date());
		
		gtag('config', 'G-WTWJEHK1C2');
		</script>
		
	</head>
	<body>
		<header>
			<i class="back layui-icon layui-icon-return"></i>
			<h1>联机房间</h1>
			<i class="new layui-icon layui-icon-addition"></i>
		</header>
		<p class="state connecting">连接服务器中……</p>
		<ul id="rooms">获取房间中……</ul>
		<section id="room" style="display: none;">
			<header>
				<i class="back layui-icon layui-icon-return"></i>
				<h2></h2>
				<i class="exit layui-icon layui-icon-close"></i>
			</header>
			<p class="state connecting">连接服务器中……</p>
			<label>房间成员</label>
			<ul id="players">加载中……</ul>
			<label>游戏设置（仅房主可修改）</label>
			<form class="setting layui-form" onsubmit="return false;">
				<div class="layui-form-item">
					<label class="layui-form-label">先手</label>
					<div class="layui-input-inline layui-btn-group">
						<button class="random layui-btn layui-btn-normal">随机</button>
						<button class="first layui-btn layui-btn-primary layui-border-green">先手</button>
						<button class="last layui-btn layui-btn-primary layui-border-green">后手</button>
					</div>
				</div>
				<div class="layui-form-item">
					<label class="layui-form-label">维数</label>
					<div class="layui-input-inline layui-btn-group">
						<button class="two layui-btn">2D</button>
						<button class="three layui-btn layui-btn-primary layui-border-green">3D</button>
						<button class="four layui-btn layui-btn-primary layui-border-green">4D</button>
					</div>
				</div>
				<div class="layui-form-item">
					<label class="layui-form-label">连子数</label>
					<div class="layui-input-inline">
						<input type="number" name="n" min="3" max="10" value="5" class="layui-input" />
					</div>
				</div>
				<div class="layui-form-item">
					<label class="layui-form-label">棋盘行数</label>
					<div class="layui-input-inline">
						<input type="number" name="rows" min="3" max="30" init="19" value="19" class="layui-input" />
					</div>
				</div>
				<div class="layui-form-item">
					<label class="layui-form-label">棋盘列数</label>
					<div class="layui-input-inline">
						<input type="number" name="cols" min="3" max="30" init="19" value="19" class="layui-input" />
					</div>
				</div>
				<div class="layui-form-item" style="display: none;">
					<label class="layui-form-label">棋盘深度</label>
					<div class="layui-input-inline">
						<input type="number" name="depth" min="3" max="30" init="10" value="10" class="layui-input" />
					</div>
				</div>
				<div class="layui-form-item" style="display: none;">
					<label class="layui-form-label">四维厚度</label>
					<div class="layui-input-inline">
						<input type="number" name="width" min="3" max="30" init="10" value="10" class="layui-input" />
					</div>
				</div>
				<div class="layui-form-item">
					<label class="layui-form-label">下棋位置</label>
					<div class="layui-input-inline">
						<input type="radio" name="place" title="格点" checked />
						<input type="radio" name="place" title="格内" />
					</div>
				</div>
			</form>
			<label>信息聊天区</label>
			<form id="info" onsubmit="return chat();">
				<div class="output layui-textarea" disabled></div>
				<div class="input">
					<input placeholder="要发送的消息" class="layui-input" />
					<button class="layui-btn layui-btn-primary layui-border-blue">发送</button>
				</div>
			</form>
			<button class="join layui-btn layui-btn-normal layui-btn-radius" style="display: none;">加入游戏</button>
			<button class="start layui-btn layui-btn-normal layui-btn-radius layui-btn-disabled" style="display: none;">开始游戏</button>
			<br/>
		</section>
		
		<footer><span>当前在线人数：</span><span class="people"></span></footer>
		
<script>
document.addEventListener("plusready", function(){
	plus.navigator.setStatusBarBackground("#aef");
	plus.navigator.setStatusBarStyle("dark");
	plus.key.addEventListener("backbutton", function(){
		go("index.html");
	});
}, false);
</script>
<script>
$("html").addClass("fadeIn");
function go(url){
	$("html").addClass(url == "index.html"? "outDown": "outHeight");
	setTimeout(function(){
		if (typeof plus != "undefined")
			if (url == "index.html"){
				plus.navigator.setStatusBarBackground("#000");
				plus.navigator.setStatusBarStyle("light");
			}else{
				plus.navigator.setStatusBarBackground("#aef");
				plus.navigator.setStatusBarStyle("dark");
			}
		location.href = url;
	}, 600);
	layer.load(0);
}


$("button, input[type='button'], header > i, #rooms > li").click(function(){
	playEffect(); //播放音效
});
setTimeout(function(){
	$("input[type='radio'], input[type='checkbox']").next().click(function(){
		playEffect(); //播放音效
	});
}, 100);


const form = $("#room > form")[0]; //表单元素

//切换先手
function setFirst(first){
	switch (first){
		case null:
			$("#room > form .random")
				.removeClass("layui-btn-primary layui-border-blue")
				.addClass("layui-btn-normal");
			$("#room > form .first")
				.addClass("layui-btn-primary layui-border-green");
			$("#room > form .last")
				.addClass("layui-btn-primary layui-border-green");
			break;
		
		case true:
			$("#room > form .random")
				.removeClass("layui-btn-normal")
				.addClass("layui-btn-primary layui-border-blue");
			$("#room > form .first")
				.removeClass("layui-btn-primary layui-border-green");
			$("#room > form .last")
				.removeClass("layui-btn-normal")
				.addClass("layui-btn-primary layui-border-green");
			break;
		
		case false:
			$("#room > form .random")
				.removeClass("layui-btn-normal")
				.addClass("layui-btn-primary layui-border-blue");
			$("#room > form .first")
				.removeClass("layui-btn-normal")
				.addClass("layui-btn-primary layui-border-green");
			$("#room > form .last")
				.removeClass("layui-btn-primary layui-border-green");
			break;
	}
}

//切换维数
function setD(D){
	switch (D){
		case 2:
			$(form).find(".two")
				.removeClass("layui-btn-primary layui-border-green")
				.siblings().addClass("layui-btn-primary layui-border-green");
			form.cols.init = form.rows.init = 19; //初始值为19
			$(form.depth).parent().parent().hide("slow");
			$(form.width).parent().parent().hide("slow");
			$(form.place).parent().parent().show("slow");
			break;
		
		case 3:
			$(form).find(".three")
				.removeClass("layui-btn-primary layui-border-green")
				.siblings().addClass("layui-btn-primary layui-border-green");
			form.cols.init = form.rows.init = form.depth.init = 10; //初始值为10
			$(form.depth).parent().parent().show("slow");
			$(form.width).parent().parent().hide("slow");
			$(form.place).parent().parent().hide("slow");
			break;
		
		case 4:
			$(form).find(".four")
				.removeClass("layui-btn-primary layui-border-green")
				.siblings().addClass("layui-btn-primary layui-border-green");
			form.cols.init = form.rows.init = form.depth.init = form.width.init = 10; //初始值为10
			$(form.depth).parent().parent().show("slow");
			$(form.width).parent().parent().show("slow");
			$(form.place).parent().parent().hide("slow");
			break;
	}
}

//更新房间设置
function updateRoomSetting(settings={}){
	const {name, first, D, N, size, place, people, owner} = settings;
	console.log("updateRoomSetting", settings)
	if (name !== undefined)
		$("#room > header > h2").html( name );
	if (first !== undefined)
		setFirst( first ); //先手
	if (D !== undefined)
		setD( D ); //维度
	if (N !== undefined)
		$(form).find("input[name='n']").val( Math.limitRange(N, 3, 10) ); //连子数
	if (size !== undefined){
		if (size.cols !== undefined)
			$(form).find("input[name='cols']").val( Math.limitRange(size.cols, 3, 30) );
		if (size.rows !== undefined)
			$(form).find("input[name='rows']").val( Math.limitRange(size.rows, 3, 30) );
		if (size.depth !== undefined)
			$(form).find("input[name='depth']").val( Math.limitRange(size.depth, 3, 30) ); //棋盘大小
		if (size.width !== undefined)
			$(form).find("input[name='width']").val( Math.limitRange(size.width, 3, 30) ); //棋盘大小
	}
	if (place !== undefined){ //下棋位置
		const input = $(form).find("input[name='place']:eq("+place+")");
		input[0].checked = true;
		layui.use("form", function(){
			const form = layui.form;
			form.render(); //重绘
		});
	}
	if (people !== undefined){
		$("#room > ul").empty(); //清空
		
		if (Object.keys(people).length == 0)
			return $("#room > ul").html("房间没有成员？这一定是bug");
		
		for (const [i,v] of Object.entries(people))
			$("#room > ul").append(
				$("<li></li>").html((i==0? "<span>房主：</span>": i==1? "<span>成员：</span>": "") + (v||"<span>（无）</span>") + (v==ID? "<span>（我）</span>": ""))
			);
		
		if (people[1] && people[0]){ //可以开始游戏
			$("#room > button.start")
				.removeAttr("disabled")
				.removeClass("layui-btn-disabled");
		}else{ //不可开始游戏
			$("#room > button.start")
				.attr("disabled", "disabled")
				.addClass("layui-btn-disabled");
		}
		
		if ( people.slice(0,2).indexOf(ID) != -1 ){ //不可加入游戏
			$("#room > button.join")
				.attr("disabled", "disabled")
				.addClass("layui-btn-disabled");
		}else{ //可加入游戏
			$("#room > button.join")
				.removeAttr("disabled")
				.removeClass("layui-btn-disabled");
		}
	}
	if (owner !== undefined){
		switch (owner){
			case true: //房主
				$("#room > form.setting button, #room > form.setting input, #room > button").removeAttr("disabled"); //房主才可以更改设置
				$("#room > .start").show(); //房主才可以开始游戏
				$("#room > .join").hide();
				break;
			case false: //成员
				$("#room > form.setting button, #room > form.setting input, #room > button").attr("disabled", "disabled"); //非房主不能更改设置
				$("#room > .start").hide(); //非房主不能开始游戏
				$("#room > .join").hide();
				break;
			case null: //游客
				$("#room > form.setting button, #room > form.setting input, #room > button").attr("disabled", "disabled"); //非房主不能更改设置
				$("#room > .start").hide(); //非房主不能开始游戏
				$("#room > .join").show();
				break;
		}
	}
}

//进入房间动画
function roomIntoAnimation(){
	console.log("roomIntoAnimation")
	if ($("#room").css("display") != "none") return; //已显示
	$("#room").show().css("left", "100%")
		.animate({
			left: "0%"
		}, "slow");
}

//离开房间动画
function roomOutAnimation(){
	console.log("roomOutAnimation")
	if ($("#room").css("display") == "none") return; //已隐藏
	$("#room").css("left", "0%")
		.animate({
			left: "100%"
		}, "slow", ()=>$("#room").hide());
}



let socket, //socket.io
	send, //send
	ID, //分配的ID
	ROOMLIST = {}, //房间列表
	ROOM = null, //加入的房间
	startRoomLoader; //开始游戏等待
if (typeof io == "undefined"){ //未加载socket.io.js
	$(".state").html("网络错误或服务器繁忙，请检查网络连接再刷新页面！")
		.removeClass().addClass("state failed");
	
}else{
	socket = io("https://wzh.glitch.me/");
	
	send = function(name, ...data){
		console.log("↑", name, data);
		socket.emit(name, ...data);
	};
	
	socket.on("connecting", function(data){
		$(".state").html("连接服务器中……")
			.removeClass().addClass("state connecting");
	});
	socket.on("connect", function(data){
		ROOM = null;
		roomOutAnimation();
		send("type", "gobang"); //type
		send("gobang_roomList"); //房间列表
		$(".state").html("服务器连接成功")
			.removeClass().addClass("state success");
		layer.msg("<span>服务器连接成功</span>", {icon:1});
	});
	socket.on("connect_failed", function(data){
		$(".state").html("服务器连接失败")
			.removeClass().addClass("state failed");
		layer.msg("<span>服务器连接失败</span>", {icon:2});
	});
	socket.on("disconnect", function(data){
		ROOM = null;
		roomOutAnimation();
		$(".state").html("与服务器连接断开")
			.removeClass().addClass("state failed");
		layer.msg("<span>与服务器连接断开</span>", {icon:2});
	});
	socket.on("reconnecting", function(data){
		$(".state").html("重连中……")
			.removeClass().addClass("state connecting");
	});
	socket.on("reconnect", function(data){
		ROOM = null;
		roomOutAnimation();
		send("type", "gobang"); //type
		send("gobang_roomList"); //房间列表
		$(".state").html("服务器重连成功")
			.removeClass().addClass("state success");
		layer.msg("<span>服务器重连成功</span>", {icon:1});
	});
	socket.on("reconnect_failed", function(data){
		$(".state").html("服务器重连失败")
			.removeClass().addClass("state failed");
		layer.msg("<span>服务器重连失败</span>", {icon:2});
	});
	socket.on("error", function(data){
		console.error(data);
		$(".state").html("服务器连接错误！")
			.removeClass().addClass("state failed");
		layer.msg("<span>服务器连接错误！</span>", {icon:2});
	});
	
	
	//分配ID
	socket.on("gobang_assignID", function(data){
		console.log("↓ gobang_assignID", data)
		ID = data;
		$(".state").html("<span>你的分配ID：</span>" + ID);
	});
	
	//当前在线人数
	socket.on("gobang_people", function(num){
		console.log("↓ gobang_people", num)
		$(".people").html(num);
	});
	
	//房间列表
	socket.on("gobang_roomList", function(list){
		console.log("↓ gobang_roomList", list)
		$("#rooms").empty(); //清空
		
		if (Object.keys(list).length == 0)
			return $("#rooms").html("暂无房间，快去创建一个吧");
		
		for (const name of Object.keys(ROOMLIST))
			if (!(name in list)) //房间不存在 删除
				delete ROOMLIST[name];
		
		for (const [name,v] of Object.entries(list)){
			ROOMLIST[name] = ROOMLIST[name] || {};
			for (const [attr, value] of Object.entries(v))
				ROOMLIST[name][attr] = value; //更新数据
			$("#rooms").append(
				$("<li></li>")
					.append(
						$("<h3></h3>").html(name)
					)
					.append(
						$("<p></p>").html("<span>房主：</span>" + v.people[0])
					)
					.append(
						$("<p></p>").html("<span>人数：</span>" + v.people.filter(v => v).length)
					)
					.append(
						$("<p></p>").html("<span>状态：</span>" + (v.state? "<span>已开始游戏</span>": "<span>等待开始游戏</span>"))
					)
					.addClass(v.state? "unable": "able")
					.click( ()=>intoRoom(name) )
			);
		}
		
		if (ROOM in ROOMLIST){
			updateRoomSetting(ROOMLIST[ROOM]);
		}else{
			ROOM = null;
			roomOutAnimation();
		}
	});
	
	/*//房间成员
	socket.on("gobang_roomPeople", function(list){
		console.log("↓ gobang_roomPeople", list)
		
		ROOMLIST[ROOM].people = list;
		
		$("#room > ul").empty(); //清空
		
		if (Object.keys(list).length == 0)
			return $("#room > ul").html("房间没有成员？这一定是bug");
		
		for (const [i,v] of Object.entries(list))
			$("#room > ul").append(
				$("<li></li>").html((i==0? "房主：": i==1? "成员：": "") + v + (v==ID? "（我）": ""))
			);
		
		if (Object.keys(list).length >= 2){ //可以开始游戏
			$("#room > button.start").removeClass("layui-btn-disabled");
		}else{ //不可开始游戏
			$("#room > button.start").addClass("layui-btn-disabled");
		}
	});*/
	
	//房间关闭
	socket.on("gobang_closeRoom", function(room){
		console.log("↓ gobang_closeRoom", room)
		layer.msg(`“${room}”<span>房间已关闭</span>`);
		ROOM = null;
		roomOutAnimation();
	});
	
	//房间设置
	socket.on("gobang_roomSettings", function(settings){
		console.log("↓ gobang_roomSettings", settings)
		ROOMLIST[ROOM] = settings;
		updateRoomSetting(settings);
	});
	
	//设置先手
	socket.on("gobang_setFirst", function(first){
		console.log("↓ gobang_setFirst", first)
		ROOMLIST[ROOM].first = first;
		setFirst(first);
	});
	
	//设置维数
	socket.on("gobang_setD", function(D){
		console.log("↓ gobang_setD", D)
		ROOMLIST[ROOM].D = D;
		setD(D);
	});
	
	//设置连子数
	socket.on("gobang_setN", function(N){
		console.log("↓ gobang_setN", N)
		ROOMLIST[ROOM].N = N;
		updateRoomSetting({N});
	});
	
	//设置棋盘大小
	socket.on("gobang_setSize", function(size){
		console.log("↓ gobang_setSize", size)
		const {cols, rows, depth, width} = size;
		ROOMLIST[ROOM].size.cols = cols,
		ROOMLIST[ROOM].size.rows = rows,
		ROOMLIST[ROOM].size.depth = depth,
		ROOMLIST[ROOM].size.width = width;
		updateRoomSetting({size});
	});
	
	//设置下棋位置
	socket.on("gobang_setPlace", function(place){
		console.log("↓ gobang_setPlace", place)
		ROOMLIST[ROOM].place = place;
		updateRoomSetting({place});
	});
	
	//进入房间
	socket.on("gobang_intoRoom", function(id){
		console.log("↓ gobang_intoRoom", id)
		
		$("#info > .output").append(
			$("<p></p>").html(`“${id}”<span>进入了房间</span>`)
				.css("text-align", "center")
		);
	});
	
	//加入游戏
	socket.on("gobang_joinRoom", function(id){
		console.log("↓ gobang_joinRoom", id)
		
		$("#info > .output").append(
			$("<p></p>").html(`“${id}”<span>加入了游戏</span>`)
				.css("text-align", "center")
		);
	});
	
	//退出房间
	socket.on("gobang_exitRoom", function(id){
		console.log("↓ gobang_exitRoom", id)
		
		$("#info > .output").append(
			$("<p></p>").html(`“${id}”<span>退出了房间</span>`)
				.css("text-align", "center")
		);
	});
	
	//聊天
	socket.on("gobang_chat", function(id, msg){
		console.log("↓ gobang_chat", id, msg)
		
		$("#info > .output").append(
			$("<p></p>").html(`${id}：${msg}`)
		);
	});
	
	//开始游戏
	socket.on("gobang_roomStart", function(room){
		console.log("↓ gobang_roomStart", room)
		const type = ROOMLIST[ROOM].people[0] == ID;
		let path;
		switch (ROOMLIST[ROOM].D){
			case 2:
				path = "online_2D.html";
				break;
			case 3:
				path = "online_3D.html";
				break;
			case 4:
				path = "online_4D.html";
				break;
		}
		go(path +
			"?id=" + ID +
			"&room=" + ROOM +
			"&type=" + +type +
			"&first=" + JSON.stringify( ROOMLIST[ROOM].first ) +
			"&N=" + ROOMLIST[ROOM].N +
			"&size=" + JSON.stringify( ROOMLIST[ROOM].size ) +
			"&place=" + ROOMLIST[ROOM].place
		);
	});
	
	
	//newRoom失败 有同名房间
	socket.on("gobang_newRoom_failed", function(room){
		console.log("↓ gobang_newRoom_failed", room)
		layer.msg("<span>创建房间失败，已有同名房间</span>", {icon: 5});
		ROOM = null;
		roomOutAnimation();
	});
	
	//closeRoom失败 房间关闭
	socket.on("gobang_closeRoom_failed", function(room){
		console.log("↓ gobang_closeRoom_failed", room)
		layer.msg("<span>关闭房间失败，房间已被关闭</span>", {icon: 5});
		ROOM = null;
		roomOutAnimation();
	});
	
	//exitRoom失败 房间关闭
	socket.on("gobang_exitRoom_failed", function(room){
		console.log("↓ gobang_exitRoom_failed", room)
		layer.msg("<span>退出房间失败，房间已被关闭</span>", {icon: 5});
		ROOM = null;
		roomOutAnimation();
	});
	
	//roomSettings失败 房间关闭
	socket.on("gobang_roomSettings_failed", function(room){
		console.log("↓ gobang_roomSettings_failed", room)
		layer.msg("<span>获取房间设置失败，房间已被关闭</span>", {icon: 5});
		ROOM = null;
		roomOutAnimation();
	});
	
	//intoRoom失败
	socket.on("gobang_intoRoom_failed", function(room){
		console.log("↓ gobang_intoRoom_failed", room)
		layer.msg("<span>进入房间失败，房间已被关闭</span>", {icon: 5});
		ROOM = null;
		roomOutAnimation();
	});
	
	//joinRoom失败
	socket.on("gobang_joinRoom_failed", function(room){
		console.log("↓ gobang_joinRoom_failed", room)
		layer.msg("<span>加入房间失败，已有人加入游戏或房间已被关闭</span>", {icon: 5});
		/*ROOM = null;
		roomOutAnimation();*/
	});
	
	//setFirst失败
	socket.on("gobang_setFirst_failed", function(room){
		console.log("↓ gobang_setFirst_failed", room)
		layer.msg("<span>设置先手失败，房间已被关闭</span>", {icon: 5});
		ROOM = null;
		roomOutAnimation();
	});
	
	//setD失败
	socket.on("gobang_setD_failed", function(room){
		console.log("↓ gobang_setD_failed", room)
		layer.msg("<span>设置维数失败，房间已被关闭</span>", {icon: 5});
		ROOM = null;
		roomOutAnimation();
	});
	
	//setN失败
	socket.on("gobang_setN_failed", function(room){
		console.log("↓ gobang_setN_failed", room)
		layer.msg("<span>设置连子数失败，房间已被关闭</span>", {icon: 5});
		ROOM = null;
		roomOutAnimation();
	});
	
	//setSize失败
	socket.on("gobang_setSize_failed", function(room){
		console.log("↓ gobang_setSize_failed", room)
		layer.msg("<span>设置棋盘大小失败，房间已被关闭</span>", {icon: 5});
		ROOM = null;
		roomOutAnimation();
	});
	
	//setPlace失败
	socket.on("gobang_setPlace_failed", function(room){
		console.log("↓ gobang_setPlace_failed", room)
		layer.msg("<span>设置下棋位置失败，房间已被关闭</span>", {icon: 5});
		ROOM = null;
		roomOutAnimation();
	});
	
	//chat失败
	socket.on("gobang_chat_failed", function(room){
		console.log("↓ gobang_chat_failed", room)
		layer.msg("<span>发送消息失败，房间已被关闭</span>", {icon: 5});
		ROOM = null;
		roomOutAnimation();
	});
	
	//roomStart失败
	socket.on("gobang_roomStart_failed", function(room){
		console.log("↓ gobang_roomStart_failed", room)
		layer.close( startRoomLoader );
		layer.msg("<span>开始游戏失败，人数不足或房间已被关闭</span>", {icon: 5});
	});
	
}



/* 返回 */
$("body > header > .back").click(function(){
	go("index.html");
});

/* 新建房间 */
$("body > header > .new").click(function(){
	if (socket.disconnected) //未连接
		return layer.msg("<span>请等待连接到服务器</span>", {icon: 5});
	
	if (ROOM)
		return layer.msg(`<span>您已加入房间</span>“${ROOM}”<span>，请先退出房间再创建</span>`, {icon: 5});
	
	layer.prompt({
		title: "请输入房间名",
		maxlength: 10
	}, function(value, index, elem){
		value = value && (value + "").trim();
		
		if (!value)
			return layer.msg("<span>请输入房间名</span>", {icon: 5});
			
		if ( ROOMLIST[value] )
			return layer.msg(`“${value}”<span>房间已存在</span>`, {icon: 5});
		
		layer.close(index);
		
		send("gobang_newRoom", value);
		ROOM = value; //默认加入房间
		
		//初始化设置
		updateRoomSetting({name: value, first: null, owner: true});
		$("#player").empty().html("加载中……");
		const setting = JSON.parse( localStorage.getItem("五子棋_游戏设置") || "{}" );
		updateRoomSetting(setting);
		
		console.log("setting", setting)
		if (setting.D)
			send("gobang_setD", ROOM, setting.D);
		if (setting.N)
			send("gobang_setN", ROOM, setting.N);
		if (setting.cols && setting.rows)
			send("gobang_setSize", ROOM, {
				cols: setting.cols,
				rows: setting.rows,
				depth: setting.depth,
				width: setting.width
			});
		if (setting.place)
			send("gobang_setPlace", ROOM, setting.place);
		
		//进入动画
		roomIntoAnimation();
	});
});

/* 进入房间 */
function intoRoom(name){
	if (socket.disconnected) //未连接
		return layer.msg("<span>请等待连接到服务器</span>", {icon: 5});
	
	roomIntoAnimation();
	
	//初始化设置
	if (ROOMLIST[name].people.indexOf(ID) != -1){ //本在房间内
		ROOM = name;
		updateRoomSetting({
			name,
			people: ROOMLIST[name].people,
			owner: ROOMLIST[name].people[0] == ID
		});
		
	}else{ //新房间
		ROOM = name;
		send("gobang_intoRoom", name);
		console.log(ROOMLIST[name].people)
		$("#player").empty().html("加载中……");
		updateRoomSetting({
			name,
			people: ROOMLIST[name].people,
			owner: null
		});
	}
}

/* 加入房间 */
$("#room > .join").click(function(){
	if (ROOMLIST[ROOM].people.slice(0,2).indexOf(ID) != -1){ //房主或成员
		$(this).hide();
		layer.msg("您已加入房间");
		
	}else{ //加入游戏
		for (const [name, room] of Object.entries(ROOMLIST))
			if (room.people.slice(0,2).indexOf(ID) != -1)
				return layer.msg(`<span>您已加入房间</span>“${name}”<span>，请先退出房间再加入</span>`, {icon: 5});
		
		if (ROOMLIST[ROOM].state != false)
			return layer.msg("<span>当前房间已开始游戏</span>", {icon: 5});
		
		if (ROOMLIST[ROOM].people[1] != null)
			return layer.msg("<span>已有人加入游戏</span>", {icon: 5});
		
		send("gobang_joinRoom", ROOM);
		
		//初始化设置
		updateRoomSetting({
			name: ROOM,
			people: ROOMLIST[ROOM].people,
			owner: false
		});
	}
});

/* 发送消息 */
$("#info > .input > button").click(chat);
function chat(){
	send("gobang_chat", ROOM, $("#info > .input > input").val());
	$("#info > .input > input").val(""); //清空输入
	return false;
}

/* 返回 */
$("#room > header >  .back").click(function(){
	if ( ROOMLIST[ROOM].people[0] != ID &&
		ROOMLIST[ROOM].people[1] != ID
	){ //不是房主和成员 退出房间
		send("gobang_exitRoom", ROOM);
		ROOM = null;
	}
	roomOutAnimation();
});

/* 解散房间 */
$("#room > header >  .exit").click(function(){
	if (ROOMLIST[ROOM].people[0] == ID){ //自己为房主
		layer.confirm(`<span>真的要关闭房间</span>“${ROOM}”<span>吗？</span>`, {
			icon: 3,
			title: "是否关闭房间"
		}, function(index){
			layer.close(index);
			
			send("gobang_closeRoom", ROOM);
			ROOM = null;
			roomOutAnimation();
		});
		
	}else if (ROOMLIST[ROOM].people[1] == ID){ //自己为成员
		layer.confirm(`<span>真的要退出房间</span>“${ROOM}”<span>吗？</span>`, {
			icon: 3,
			title: "是否退出房间"
		}, function(index){
			layer.close(index);
			
			send("gobang_exitRoom", ROOM);
			ROOM = null;
			roomOutAnimation();
		});
		
	}else{ //自己为游客
		send("gobang_exitRoom", ROOM);
		ROOM = null;
		roomOutAnimation();
	}
});


/* 设置 */
//先手
$("#room > form .random").click(function(){
	if (ROOMLIST[ROOM].people[0] != ID) return; //非房主无法操作
	send("gobang_setFirst", ROOM, null);
	ROOMLIST[ROOM].first = null;
	setFirst(null);
});
$("#room > form .first").click(function(){
	if (ROOMLIST[ROOM].people[0] != ID) return; //非房主无法操作
	send("gobang_setFirst", ROOM, true);
	ROOMLIST[ROOM].first = true;
	setFirst(true);
});
$("#room > form .last").click(function(){
	if (ROOMLIST[ROOM].people[0] != ID) return; //非房主无法操作
	send("gobang_setFirst", ROOM, false);
	ROOMLIST[ROOM].first = false;
	setFirst(false);
});

//维数
$("#room > form .two").click(function(){
	if (ROOMLIST[ROOM].people[0] != ID) return; //非房主无法操作
	send("gobang_setD", ROOM, 2);
	ROOMLIST[ROOM].D = 2;
	setD(2);
});
$("#room > form .three").click(function(){
	if (ROOMLIST[ROOM].people[0] != ID) return; //非房主无法操作
	send("gobang_setD", ROOM, 3);
	ROOMLIST[ROOM].D = 3;
	setD(3);
});
$("#room > form .four").click(function(){
	if (ROOMLIST[ROOM].people[0] != ID) return; //非房主无法操作
	send("gobang_setD", ROOM, 4);
	ROOMLIST[ROOM].D = 4;
	setD(4);
});

//输入改变
$("#room > form input[type='number']").change(function(){
	if (this.value == "")
		return (this.value = this.init); //初始值
	this.value = Math.limitRange(+this.value, +this.min, +this.max);
});

//连子数
$("#room > form input[name='n']").change(function(){
	if (ROOMLIST[ROOM].people[0] != ID) return; //非房主无法操作
	send("gobang_setN", ROOM, +this.value);
});

//棋盘大小
$("#room > form input[name='cols'], #room > form input[name='rows']").change(function(){
	if (ROOMLIST[ROOM].people[0] != ID) return; //非房主无法操作
	send("gobang_setSize", ROOM, {
		cols: +$("#room > form input[name='cols']").val(),
		rows: +$("#room > form input[name='rows']").val(),
		depth: +$("#room > form input[name='depth']").val(),
		width: +$("#room > form input[name='width']").val()
	});
});

//下棋位置
$("#room > form input[name='place']").parent().click(function(){
	if (ROOMLIST[ROOM] && ROOMLIST[ROOM].people[0] != ID) return; //非房主无法操作
	send("gobang_setPlace", ROOM, +$("#room > form input[name='place']")[1].checked);
});


//开始游戏
$("#room > .start").click(function(){
	if (ROOMLIST[ROOM].people.length < 2)
		return layer.msg("<span>人数不足，无法开始游戏</span>", {icon: 5});
	
	send("gobang_roomStart", ROOM);
	startRoomLoader = layer.load(1);
});



/* 电脑版按键 */
document.onkeydown = function(e){
	console.log(e.key)
	if (e.key == "Escape"){
		go("index.html");
	}
	e.preventDefault();
	return false;
} 
</script>
		
	</body>
</html>
